/*
 * hfsset.cpp - configure handsfree
 *
 * Copyright (C) 2010-2011 Serge Begger
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "hfsset.h"
#include "ui_hfsset.h"
#include "bluez/types.h"

hfsset::hfsset(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::hfsset)
{
    ui->setupUi(this);
    btActive = false;
    adapterPath = "";

    btActive = initBT();

    settings = new QSettings("carpc", "handsfree", this);
    settings->setPath(QSettings::IniFormat,QSettings::UserScope,"carpc");
    currDevName = settings->value("devName").toString();
    currDevAddr = settings->value("devAddr").toString();
    currDevConn = false;

    if(!currDevAddr.isEmpty()) {
        ui->BTcmbBox->addItem(currDevName,currDevAddr);
        ui->BTcmbBox->setCurrentIndex(0);
        currDevConn = deviceIsConnected();
    }

    ui->connectDevice->setDisabled(currDevConn);
    ui->disconnectDevice->setDisabled(!currDevConn);

    connect(ui->BTcmbBox, SIGNAL(activated(int)),this, SLOT(changeDev(int)));

    pinPanel = new numPanel(this,true,QRect(0,-10,300,400));
    pinPanel->helpLabel->setText("Enter PIN code:");
    pinPanel->numAsButton->setDisabled(true);
    connect(pinPanel, SIGNAL(endPutFreq()), this, SLOT(pairedDevice()));
}

hfsset::~hfsset()
{
    if (btActive) {
        QString agentPath = AGENT_BASE;
        agentPath.append(adapterPath.split("/").last());
        adapter->UnregisterAgent(QDBusObjectPath(agentPath));
    }
    delete ui;
}

bool hfsset::deviceIsConnected()
{
    if (btActive) {
        QDBusPendingReply<QDBusObjectPath> device = adapter->FindDevice(currDevAddr);
        device.waitForFinished();
        if (device.isValid())
            return true;
    }
    return false;
}

bool hfsset::initBT()
{
    manager = new OrgBluezManagerInterface(QString("org.bluez"), QString("/"), QDBusConnection::systemBus(),this);
    QDBusPendingReply<QVariantMap> dprops = manager->GetProperties();
    dprops.waitForFinished();

    if (!dprops.isValid()) {
        myMessage message(0);
        message.exec(0,"Received unvalid reply");
        return false;
    }

    QDBusPendingReply<QDBusObjectPath> pathDefAdapter = manager->DefaultAdapter();
    pathDefAdapter.waitForFinished();

    if (!pathDefAdapter.isValid()) {
        myMessage message(0);
        message.exec(0,"Not default BT adapter");
        return false;
    }
    adapterPath = pathDefAdapter.value().path();
    adapter = new OrgBluezAdapterInterface(QString("org.bluez"), pathDefAdapter.value().path() , QDBusConnection::systemBus(),this);
    connect(adapter, SIGNAL(DeviceFound(QString,QVariantMap)),
                            this, SLOT(addBTDevice(QString,QVariantMap)));
    return true;
}

void hfsset::on_connectDevice_pressed()
{
    if(btActive)
        pinPanel->onShow();
}

void hfsset::on_disconnectDevice_pressed()
{
    if(btActive && currDevConn) {
        QDBusPendingReply<QDBusObjectPath> reply;
        reply = adapter->FindDevice(currDevAddr);
        adapter->RemoveDevice(reply.value());
        settings->setValue("devConn",false);
        ui->connectDevice->setDisabled(false);
        ui->disconnectDevice->setDisabled(true);
        emit disconnectDevice();
    }

}

void hfsset::pairedDevice()
{
    if(!currDevAddr.isEmpty()) {
        QString agentPath = AGENT_BASE;
        agentPath.append(
        adapter->path().split("/").last());
        QString address = currDevAddr;
        agentPath.append("/" + address.replace(":", "_"));

        ManagerAgent *agent = new ManagerAgent(agentPath, this);
        QString pin = pinPanel->freq->toLatin1();
        agent->setPinCode(pin);

        new AgentAdaptor(agent);
        QDBusConnection::systemBus().registerObject(agentPath, agent);

        QDBusPendingReply<QDBusObjectPath> reply;
        reply = adapter->CreatePairedDevice(
                                currDevAddr,
                                QDBusObjectPath(agentPath),
                                QString(AGENT_CAPABILITIES));
        QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
                        reply, this);
        connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
                        this,
                        SLOT(pairedFinished(QDBusPendingCallWatcher*)));

    }
}

void hfsset::pairedFinished(QDBusPendingCallWatcher *watcher)
{
    myMessage message(0);

    if (watcher->isError() || watcher->reply().signature() != "o") {
        watcher->error().type();
        message.exec(0,"Error "+ watcher->error().message());
        return;
    }

    QDBusObjectPath path;
    path = watcher->reply().arguments()[0].value<QDBusObjectPath>();
    message.exec(1,"Device "+ currDevName+" connected!");
    adapter->StopDiscovery();
    currDevConn = true;
    ui->connectDevice->setDisabled(currDevConn);
    ui->disconnectDevice->setDisabled(false);
    settings->setValue("devConn",currDevConn);
    emit connectDevice();
}

void hfsset::on_updateDevices_pressed()
{
    if(!btActive)
        return;
    adapter->StopDiscovery();
    ui->BTcmbBox->clear();
    ui->updateDevices->setDisabled(true);
    ui->connectDevice->setDisabled(false);
    adapter->StartDiscovery();
}

void hfsset::addBTDevice(const QString &address,
                         const QVariantMap &values)
{
    if (ui->BTcmbBox->findData(address) > -1)
        return;
    QString devName = values["Name"].toString();
    ui->BTcmbBox->addItem(devName,address);
    if (ui->BTcmbBox->count() > 0) {
        currDevName = ui->BTcmbBox->currentText();
        currDevAddr = ui->BTcmbBox->itemData(ui->BTcmbBox->currentIndex()).toString();
        changeDev(ui->BTcmbBox->currentIndex());
    }
    ui->updateDevices->setDisabled(false);
}

void hfsset::changeDev(int index)
{
    currDevName = ui->BTcmbBox->itemText(index);
    currDevAddr = ui->BTcmbBox->itemData(index).toString();
    settings->setValue("devName",currDevName);
    settings->setValue("devAddr",currDevAddr);

    currDevConn = deviceIsConnected();
    settings->setValue("devConn",currDevConn);
    ui->connectDevice->setDisabled(currDevConn);
    ui->disconnectDevice->setDisabled(!currDevConn);
}
